package com.pricetag.components;

import java.io.IOException;
import java.util.List;

import android.content.Context;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.Size;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import com.pricetag.helpers.Utils;

public class CameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
	private SurfaceHolder holder;
	private Camera camera;
	private IHasCameraComponent componentWithCamera;
	private boolean isCameraBusy = false;

	@SuppressWarnings("deprecation")
	public CameraSurfaceView(Context context) {
		super(context);

		// Initiate the Surface Holder properly
		this.holder = this.getHolder();
		this.holder.addCallback(this);
		this.holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
	}

	@SuppressWarnings("deprecation")
	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		try {
			if (this.camera != null) {
				this.camera.stopPreview();
				this.camera.release();
				this.camera = null;
			}

			// Open the Camera in preview mode
			int tryCount = 3;
			while (tryCount >= 0) {
				this.camera = Utils.openCameraSafely();
				if (this.camera != null) {
					break;
				}
			}

			this.camera.setDisplayOrientation(90);
			this.camera.setPreviewDisplay(this.holder);

			Camera.Parameters parameters = camera.getParameters();

			// Set camera orientation
			parameters.setRotation(90);

			// Set picture size
			List<Size> pictureSizes = parameters.getSupportedPictureSizes();
			for (Size size : pictureSizes) {
				if (size.width == 640 && size.height == 480) {
					parameters.setPictureSize(640, 480);
					break;
				}
			}

			// Set picture format
			List<Integer> pictureFormats = parameters.getSupportedPictureFormats();
			if (pictureFormats.contains(PixelFormat.JPEG)) {
				parameters.setPictureFormat(PixelFormat.JPEG);
			}

			// Set autofocus mode
			List<String> focusModes = parameters.getSupportedFocusModes();
			if (focusModes.contains(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
				parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
			} else if (focusModes.contains(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
				parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
			} else if (focusModes.contains(Parameters.FOCUS_MODE_AUTO)) {
				parameters.setFocusMode(Parameters.FOCUS_MODE_AUTO);
			}
			camera.setParameters(parameters);

		} catch (IOException ioe) {
			ioe.printStackTrace(System.out);
		}
	}

	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
		camera.startPreview();
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		// Surface will be destroyed when replaced with a new screen
		// Always make sure to release the Camera instance
		camera.stopPreview();
		camera.release();
		camera = null;
	}

	public Camera getCamera() {
		return this.camera;
	}

	public void takePicture(IHasCameraComponent component) {
		if (this.camera == null || this.isCameraBusy == true) {
			return;
		}
		this.isCameraBusy = true;
		componentWithCamera = component;
		this.camera.autoFocus(new AutoFocusCallbackHandler());
	}

	private class AutoFocusCallbackHandler implements Camera.AutoFocusCallback {
		@Override
		public void onAutoFocus(boolean success, Camera camera) {
			camera.takePicture(null, null, new TakePictureJPEGCallbackHandler());
		}
	}

	private class TakePictureJPEGCallbackHandler implements Camera.PictureCallback {

		@Override
		public void onPictureTaken(final byte[] data, Camera camera) {
			isCameraBusy = false;
			if (componentWithCamera instanceof IHasCameraComponent) {
				((IHasCameraComponent) componentWithCamera).setImageReady(true, data);
			}
		}

	}

	public void refreshCamera() {
		if (isCameraBusy == true || this.camera == null) {
			return;
		}
		this.isCameraBusy = true;
		camera.startPreview();
		this.isCameraBusy = false;
	}
}